-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local device_object = require 'mc.mdb.device_tree.device_object'
local default_pwm_channel = require 'device_tree.adapters.thermal_common.pwm_channel'
local log = require 'mc.logging'

local fan = device_object('Fan')

local RET_ERR<const> = 1
local RET_OK<const>  = 0

local identify_status<const> = {
    UNIDENTIFIED = 0,
    IDENTIFYING = 1,
    IDENTIFIED = 2,
    IDENTIFY_FAILED = 3
}

function fan:ctor()
    self.pwm_channel = default_pwm_channel.new(self)
end

function fan:configurable()
    return self.pwm_channel:configurable()
end

function fan:is_identified()
    return self.IdentifyStatus == identify_status.IDENTIFIED
end

function fan:get_present()
    return self.RearPresence
end

function fan:set_pwm(pwm_percent)
    local pwm_value = pwm_percent / 100 * self.MaxSupportedPWM
    -- 设置pwm，四舍五入
    self.HardwarePWM = math.floor(pwm_value + 0.5)
    self.ExpectedPWM = math.floor(pwm_value + 0.5)
    log:debug("pwm_percent(%s) set pwm_value: %s, HardwarePWM: %s", pwm_percent, pwm_value, self.HardwarePWM)
end

function fan:set_expected_pwm(pwm)
    self.ExpectedPWM = math.floor(pwm + 0.5)
end

function fan:set_pwm_channel(pwm_channel)
    self.pwm_channel = pwm_channel
end

--- @description 设置风扇转速（无校验）
--- @param pwm_percent number 
function fan:set_fan_hardware_pwm(pwm_percent)
    self.pwm_channel:set_fan_hardware_pwm(pwm_percent)
end

--- @description 设置风扇转速（有校验）
--- @param pwm_value number
--- @return 0|1
function fan:set_fan_pwm(pwm_value)
    if self.pwm_channel.set_fan_pwm then
        return self.pwm_channel:set_fan_pwm(pwm_value)
    end
    if not self:configurable() then
        return RET_ERR
    end
    local ok, ret = pcall(function ()
        self:set_fan_hardware_pwm(pwm_value)
    end)
    if not ok then
        log:error("set pwm_value(%s) failed. ret: %s", pwm_value, ret)
        return RET_ERR
    end
    return RET_OK
end

function fan:set_fan_expected_pwm(pwm_percent)
    self.pwm_channel:set_fan_expected_pwm(pwm_percent)
end

function fan:init()
    -- 设置期望转速（批量调速后调用）
    self:declare_method('Fan', 'bmc.dev.Fan', 'SetFanExpectedPWM', function (...)
        self:set_fan_expected_pwm(...)
    end)
    -- 设置风扇转速（有校验）
    self:declare_method('Fan', 'bmc.dev.Fan', 'SetFanPWM', function (...)
        self:set_fan_pwm(...)
    end)
    -- 设置风扇转速（无校验）
    self:declare_method('Fan', 'bmc.dev.Fan', 'SetFanHardwarePWM', function (...)
        return self:set_fan_hardware_pwm(...)
    end)
    -- 风扇当前是否支持调速
    self:declare_method('Fan', 'bmc.dev.Fan', 'Configurable', function ()
        return self:configurable()
    end)
end

return fan